package com.xavier.dong.netty.dubborpc.netty;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;

import java.util.concurrent.Callable;

/**
 * @author XavierDong
 **/
public class NettyClientHandler extends ChannelInboundHandlerAdapter implements Callable {


    private ChannelHandlerContext channelHandlerContext;
    private String result;  // 将来 调用后，返回的结果
    private String param; // 客户端 调用方法时，传入的参数


    /**
     * 与服务器的 连接 创建成功后 就会被 调用. 第一个被 调用
     *
     * @param ctx
     * @throws Exception
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        // 因为 在 其他方法中 会使用到 这个 ctx
        this.channelHandlerContext = ctx;
    }


    /**
     * 收到 服务器的数据后，就会调用
     * <p>
     * notify(); 唤醒 等待的线程
     *
     * @param ctx
     * @param msg
     * @throws Exception
     */
    @Override
    public synchronized void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        this.result = msg.toString();
        notify();
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        ctx.close();
    }

    /**
     * 被代理对象 调用
     * <p>
     * 发送数据给 服务器, 等待被唤醒 (wait)，再返回结果
     *
     * @return
     * @throws Exception
     */
    @Override
    public synchronized Object call() throws Exception {
        this.channelHandlerContext.writeAndFlush(this.param);

        wait(); // 等待被唤醒，获取到 服务器的结果后，唤醒
        return this.result;  // 服务方返回的结果
    }

    /**
     * 第二个被调用
     *
     * @param param
     */
    public void setParam(String param) {
        this.param = param;
    }
}
